package com.itheima.system.service.impl;

import com.aliyun.oss.OSS;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.MatchMode;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyun.oss.model.PolicyConditions;
import com.aliyun.oss.model.PutObjectResult;
import com.baidu.aip.util.Base64Util;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.itheima.common.entity.PageResult;
import com.itheima.common.entity.Result;
import com.itheima.common.entity.ResultCode;
import com.itheima.common.enums.ExceptionEnum;
import com.itheima.common.exception.IhrmException;
import com.itheima.common.utils.JwtUtils;
import com.itheima.common.utils.PermissionConstants;
import com.itheima.system.client.DepartmentFeignClient;
import com.itheima.system.mapper.UserMapper;
import com.itheima.system.pojo.Permission;
import com.itheima.system.pojo.Role;
import com.itheima.system.pojo.User;
import com.itheima.system.pojo.oss.OOSProperties;
import com.itheima.system.pojo.vo.AssignRoleVo;
import com.itheima.system.pojo.vo.UserInfo;
import com.itheima.system.pojo.vo.UserSimpleVo;
import com.itheima.system.service.PermissionService;
import com.itheima.system.service.UserService;
import com.itheima.common.utils.DateUtils;
import com.itheima.common.utils.IdWorker;
import com.itheima.system.utils.BaiDuAiUtils;
import io.jsonwebtoken.Claims;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.*;

/**
 * @author IntelliJ IDEA
 * @date 2020/10/23  10:33
 */
@Service
@Transactional
public class UserServiceImpl implements UserService {

    @Autowired
    private IdWorker idWorker;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private PermissionService permissionService;

    private static final String COADMIN="coAdmin";

    private static final String USER="user";

//    private static final String SAASADMIN="saasAdmin";

    private static final String HASNOTDEPT="0";

    private static final String HASDEPT="1";

//    private static final String DEFAULTSERVICESTATUS="1";
//
//    private static final String DEFAULTSTATUS="1";
//
//    private static final String DEFAULTPASSWORD="123456";


    @Autowired
    private OOSProperties prop;

    @Autowired
    private OSS client;

    @Autowired
    private BaiDuAiUtils baiDuAiUtils;


    /**
     * 新增用户
     */
    @Override
    public Integer addUser(User user) {
        user.setId(String.valueOf(idWorker.nextId()));
        user.setCreateTime(new Date());
        //设置初始密码
        user.setPassword(new Md5Hash(user.getPassword(),user.getPassword(),3).toString());
        //默认开启状态
        user.setEnableState("1");
        user.setLevel("user");
        //调用mapper执行新增
        return userMapper.addUser(user);
    }

    /**
     * 分页查询用户列表
     */
    @Override
    public PageResult<User> findAllUserByPage(Integer page, Integer size, Map<String,Object> map) {
        //获取参数
        String hasDept = (String) map.get("hasDept");
        String companyId = (String) map.get("companyId");
        String departmentId=(String) map.get("departmentId");
        //参数的健壮性判断
        if(StringUtils.isNotBlank(hasDept)){
            if(!StringUtils.equals(hasDept,HASNOTDEPT) && !StringUtils.equals(hasDept,HASDEPT)){
                throw new IhrmException(ExceptionEnum.INVALID_PARAM_ERROR);
            }
        }
        //设置分页参数信息 PageHelper是mybatis的分页插件
        PageHelper.startPage(page,size);
        List<User> userList = userMapper.findAllUserByPage(hasDept, companyId, departmentId);
        //处理页面显示时间格式问题
        for (User user : userList) {
            user.setTimeStyle(DateUtils.parseDateToString(user.getTimeOfEntry(),"yyyy-MM-dd HH:mm:ss").substring(0,10));
        }
        //封装PageInfo对象
        PageInfo<User> info=new PageInfo<User>(userList);
        return new PageResult<User>(info.getTotal(),info.getList());
    }

    /**
     * 根据用户id查询用户
     */
    @Override
    public User findUserById(String id) {
        return userMapper.findUserById(id);
    }

    /**
     * 根据id删除用户
     */
    @Override
    public Integer deleteUserById(String id) {
        return userMapper.deleteUserById(id);
    }

    /**
     * 修改用户
     */
    @Override
    public Integer updateUserByUserId(User user) {
        return userMapper.updateUserByUserId(user);
    }

    /**
     * 根据手机号查询用户
     */
    public User findUserByPhone(String mobile){
        return userMapper.findUserByMobile(mobile);
    }

    /**
     * 给用户分配角色
     */
    @Override
    public void assignRoles(AssignRoleVo assignRoleVo) {
        //根据用户的id查询用户
        User user=userMapper.findUserById(assignRoleVo.getId());
        //根据user_id删除中间表pe_user_role
        userMapper.deleteUserAndRoleByUserId(user.getId());
        //根据传递过的角色Ids查询角色
        userMapper.assignRoles(user.getId(),assignRoleVo.getRoleIds());
    }


    /**
     * shiro登录
     * 登录成功后返回用户的sessionId
     */
//    @Override
//    public String login(User user) {
//        UsernamePasswordToken upToken=new UsernamePasswordToken(user.getMobile(),new Md5Hash(user.getPassword(),user.getMobile(),3).toString());
//        Subject subject = SecurityUtils.getSubject();
//        subject.login(upToken);
//        //登录成功返回sessionId
//        return subject.getSession().getId().toString();
//    }


    /**
     * shiro获取用户信息
     */
//    @Override
//    public Result profile(HttpServletRequest request) {
//        String userInfo = (String) SecurityUtils.getSubject().getPrincipal();
//        if(StringUtils.isNotBlank(userInfo)){
//            Gson gson=new Gson();
//            UserInfo info = gson.fromJson(userInfo, UserInfo.class);
//            return new Result(ResultCode.SUCCESS,info);
//        }
//        return new Result(ResultCode.UNAUTHENTICATED);
//    }


    /**
     *  根据用户id查询角色,权限
     */
    @Override
    public User findUserAndRoleAndPermission(String userId) {
        return userMapper.findUserAndRoleAndPermission(userId);
    }

    /**
     *
     * JWT登录
     * 用户登录获取token字符串
     * token 数据包括companyId companyName apis(可访问的api)
     */
    @Override
    public String login(User user) {
        //获取手机号，根据手机号登录
        User u = userMapper.findUserByMobile(user.getMobile());
        if(u==null && !StringUtils.equals(user.getPassword(),u.getPassword())){
            throw new IhrmException(ResultCode.USERNOTFOUNDORPASSWORDERROR);
        }
        //token中的私密数据
        Map<String,Object> map=new HashMap<String,Object>(0);
        //根据用户id查询用户的RBAC角色权限信息（用户--->角色--->权限）
        User userInfo = this.findUserAndRoleAndPermission(u.getId());
        if(userInfo!=null){
            String apis=null;
            StringBuilder builder=new StringBuilder();
            if(!CollectionUtils.isEmpty(userInfo.getRole())){
                for (Role role : userInfo.getRole()) {
                    if(!CollectionUtils.isEmpty(role.getPermissions())){
                        for (Permission permission : role.getPermissions()) {
                            if(StringUtils.equals(String.valueOf(permission.getType()), String.valueOf(PermissionConstants.PERMISSION_API))){
                                builder.append(permission.getCode()).append(",");
                            }
                        }
                    }
                }
                apis=builder.toString();
            }
            map.put("apis",apis);
            map.put("companyId",u.getCompanyId());
            map.put("companyName",u.getCompanyName());
            return JwtUtils.createJwt(u.getId(),u.getUsername(),map);
        }
        throw new IhrmException(ResultCode.FAIL);
    }


    /**
     * JWT获取用户信息
     * @param request   request请求
     * @param claims    JWT中用户的私密数据
     * @return         返回用户个人信息
     */
    @Override
    public Result profile(HttpServletRequest request, Claims claims) {
        //获取session与对象中
        if(claims!=null){
            //获取userId
            String userId = claims.getId();
            //获取用户信息(用户--->角色--->权限)
            User user = this.findUserAndRoleAndPermission(userId);
            if(StringUtils.equals(USER,user.getLevel())){
                //普通用户
                return new Result(ResultCode.SUCCESS,new UserInfo(user));
            }else{
                //SAAS用户和COADMIN的情况
                //type      查询菜单+按钮，如果为1，查询全部，type为其他，抛异常
                //envisble  可见性，0 查询所有saas平台的最高权限   1 查询企业的权限
                //pid    权限父id
                Map<String,Object> map=new HashMap<String,Object>(0);
                if(StringUtils.equals(COADMIN,user.getLevel())){
                    //企业用户
                    map.put("envisble","1");
                }
                List<Permission> permissionList=permissionService.findAllPermission(map);
                return new Result(ResultCode.SUCCESS,new UserInfo(user,permissionList));
            }
        }else {
            throw new IhrmException(ResultCode.USEREXPRIE);
        }
    }

    @Override
    public List<UserSimpleVo> simple(String companyId) {
        List<UserSimpleVo> userSimpleVoList=new ArrayList<UserSimpleVo>(0);
        List<User> users = userMapper.findAllUserByPage(null, companyId, null);
        users.forEach(user -> {
            userSimpleVoList.add(new UserSimpleVo(user.getId(),user.getUsername()));
        });
        return userSimpleVoList;
    }

    /**
     * excel批量导入用户
     */
    @Override
    public void savaAll(List<User> userList, String companyId, String companyName) {
        //批量保存
        userMapper.saveAll(userList);
    }

    /**
     *  头像上传(base64保存在数据库中)
     */
//    @Override
//    public void uploadImg(String id, MultipartFile file) throws IOException {
//        if(file!=null){
//            //1. 根据用户id查询用户
//            User user = userMapper.findUserById(id);
//            //2. file转为dataurl格式数据
//            String dataurl ="data:image/jpg;base64,"+ Base64.encode(file.getBytes()).toString();
//            user.setStaffPhoto(dataurl);
//            //3. 执行更新
//            userMapper.updateUserByUserId(user);
//        }
//    }

    /**
     * 头像上传至OSS中的buket
     * 最后返回图片在OSS中的地址
     */
    public String uploadImg(String userId,MultipartFile file) throws Exception{
        //图片的base64编码
        String image= Base64Util.encode(file.getBytes());
        //创建上传Object的Metadata
        ObjectMetadata metadata = new ObjectMetadata();
        //上传的文件的长度
        metadata.setContentLength(file.getInputStream().available());
        //指定该Object被下载时的网页的缓存行为
        metadata.setCacheControl("no-cache");
        //指定该Object下设置Header
        metadata.setHeader("Pragma", "no-cache");
        //指定该Object被下载时的内容编码格式
        metadata.setContentEncoding("utf-8");
        //文件的MIME，定义文件的类型及网页编码，决定浏览器将以什么形式、什么编码读取文件。如果用户没有指定则根据Key或文件名的扩展名生成，
        //如果没有扩展名则填默认值application/octet-stream
        metadata.setContentType(prop.getContentType());
        //指定该Object被下载时的名称（指示MINME用户代理如何显示附加的文件，打开或下载，及文件名称）
        metadata.setContentDisposition("filename/filesize=" + file.getOriginalFilename() + "/" + file.getSize() + "Byte.");
        //上传文件   (上传文件流的形式)
        PutObjectResult putResult = client.putObject(prop.getBuketName(), prop.getDir()+userId, file.getInputStream(), metadata);
        //解析结果
        if(putResult!=null){
            //根据id查询用户
            User user = userMapper.findUserById(userId);
            user.setStaffPhoto(prop.getOssurl()+userId);
            //阿里云服务器上图片地址入数据库保存
            userMapper.updateUserByUserId(user);
            //先判断该人脸在百度云AI库中存不存在
            Boolean boo = baiDuAiUtils.faceExists(userId);
            if(BooleanUtils.isTrue(boo)){
                //存在，更新
                baiDuAiUtils.faceUpdate(userId,image);
            }else{
                //不存在，注册
                baiDuAiUtils.faceRegister(userId,image);
            }
            return prop.getOssurl()+userId;
        }
        return null;
    }

}
